package wangxiaotao.exception;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.databind.JsonMappingException;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.ShiroException;
import org.apache.shiro.authc.*;
import org.apache.shiro.authc.pam.UnsupportedTokenException;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.HostUnauthorizedException;
import org.apache.shiro.authz.UnauthenticatedException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import wangxiaotao.common.CommonResult;
import wangxiaotao.shiro.exception.PermissionException;

import javax.validation.ValidationException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * shiro认证异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = ShiroException.class)
    public CommonResult handlerShiroException(ShiroException e){
        e.printStackTrace();
        CommonResult result = new CommonResult();
        result.setCode(400);
        if (e instanceof LockedAccountException){
            result.setMessage("帐号已被锁定");
        }else if(e instanceof DisabledAccountException){
            result.setMessage("禁用的帐号");
        }else if(e instanceof UnknownAccountException){
            result.setMessage("未知的账户");
        }else if(e instanceof ExcessiveAttemptsException){
            result.setMessage("登录失败次数过多");
        }else if(e instanceof IncorrectCredentialsException){
            result.setMessage("密码错误");
        }else if(e instanceof ExpiredCredentialsException){
            result.setMessage("ExpiredCredentialsException");
        }else if (e instanceof UnsupportedTokenException){
            result.setMessage("Realm does not support authentication token");
        }else if (e instanceof AuthenticationException){
            result.setMessage("Realm does not support authentication token");
        }else
            result.setMessage(StrUtil.isNotBlank(e.getMessage())?e.getMessage():e.getClass().getName());
        return result;
    }

    /**
     * 角色校验异常   需要跳转登录
     * @param e
     * @return
     */
    @ExceptionHandler(value = AuthorizationException.class)
    public CommonResult handlerAuthorizationHandler(AuthorizationException e){
        CommonResult result = new CommonResult();
        result.setCode(401);
        if (e instanceof HostUnauthorizedException){
            result.setMessage("HostUnauthorizedException");
        }else if (e instanceof UnauthenticatedException){
            result.setMessage("无权访问，请先登录");
        }else if (e instanceof UnauthorizedException){
            result.setMessage("无权访问");
        }else
            result.setMessage("AuthorizationException");
        return result;
    }

    /**
     * 文件操作异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = MinioException.class)
    public CommonResult handlerMinioException(MinioException e){
        return CommonResult.fail("文件操作异常："+e.getMessage(),null);
    }

    /**
     * 权限异常  需要跳转登录
     * @param e
     * @return 401
     */
    @ExceptionHandler(value = PermissionException.class)
    public CommonResult handlerPermissionException(PermissionException e){
        return new CommonResult(401,e.getMessage());
    }

    /**
     * 实体类校验异常
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    public CommonResult handlerBindException(BindException e){
        List<ObjectError> allErrors = e.getAllErrors();
        log.error(String.valueOf(CollectionUtil.isNotEmpty(allErrors)));
        if (CollectionUtil.isNotEmpty(allErrors)){
            List<String> errors = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.toList());
            return CommonResult.fail(String.valueOf(errors),null);
        }
        return CommonResult.fail("BindException:"+e.getMessage());
    }

    /**
     * jackson错误
     * @param e
     * @return
     */
    @ExceptionHandler(value = JacksonException.class)
    public CommonResult handlerJacksonException(JacksonException e){
        e.printStackTrace();
        if (e instanceof JsonMappingException){
            return CommonResult.fail("数据类型转换异常:"+e.getMessage(),null);
        }
        return CommonResult.fail("JacksonException:"+e.getMessage());
    }

    @ExceptionHandler(value = ValidationException.class)
    public CommonResult handlerValidationException(ValidationException e){
        e.printStackTrace();
        return CommonResult.fail("实体类校验异常:"+e.getMessage(),null);
    }

    @ExceptionHandler(value = Exception.class)
    public CommonResult allHandler(Exception e){
        e.printStackTrace();
        return CommonResult.fail(400,StrUtil.isNotEmpty(e.getMessage())?e.getMessage(): String.valueOf(e.getClass()),null);
    }
}
